import {Component, Input, OnInit, Optional, Self, ViewChild} from '@angular/core';
import {FormControlName} from '@angular/forms';
import {Subscription} from 'rxjs';

@Component({
  selector: 'ng-tools-number-input',
  templateUrl: './number-input.component.html',
  styleUrls: ['./number-input.component.scss']
})
export class NumberInputComponent implements OnInit {
  private reg: RegExp;
  private oldValue = null;
  private interval;
  private controlValueSubscription: Subscription;
  @ViewChild('inputElem') private inputRef;

  @Input() unit: string;
  @Input() max = 999999999;
  @Input() min = 1;
  inputValue: any = 0;

  constructor(@Optional() @Self() private formControlName: FormControlName) {
  }

  get input() {
    return this.inputRef.nativeElement;
  }

  /** get input value without unit */
  get numberInValue() {
    if (this.unit) {
      const unitIndex = this.inputValue.toString().indexOf(this.unit);
      if (unitIndex > 1) {
        return parseInt(this.inputValue.toString().slice(0, unitIndex), 0);
      }
    }
    return parseInt(this.inputValue, 0);
  }

  ngOnInit() {
    let controlValue = null;
    if (this.formControlName) {
      controlValue = this.formControlName.control.value;
      /** 观察control value的变化，然后更新到input */
      this.controlValueSubscription = this.formControlName.control.valueChanges.subscribe((next) => {
        this.inputValue = next;
        this.updateInput(this.input);
      });
    }
    if (controlValue) {
      this.inputValue = controlValue;
    } else {
      this.inputValue = this.min;
    }

    /** 追加单位和创建正则表达式 */
    let pattern;
    if (this.unit) {
      this.inputValue = this.inputValue.toString() + this.unit;
      pattern = `^-?[1-9][0-9]*${this.unit}?$`;
    } else {
      this.inputValue = this.inputValue.toString();
      pattern = `^-?[1-9][0-9]*$`;
    }
    this.reg = new RegExp(pattern);
    this.updateInput(this.input);
  }

  match() {
    return this.inputValue.toString().match(this.reg) !== null;
  }


  increase() {
    if (this.match()) {
      this.inputValue = this.numberInValue + 1;
      this.updateInput(this.input);
    }
  }

  intervalIncrease() {
    if (this.match()) {
      this.interval = setInterval(() => {
        if (this.numberInValue < this.max) {
          this.inputValue = this.numberInValue + 1;
          this.updateInput(this.input);
        } else {
          this.clearInterval();
        }
      }, 100);
    }
  }

  clearInterval() {
    clearInterval(this.interval);
  }

  decrease() {
    if (this.match() && this.numberInValue > this.min) {
      this.inputValue = this.numberInValue - 1;
      this.updateInput(this.input);
    }
  }

  intervalDecrease() {
    if (this.match()) {
      this.interval = setInterval(() => {
        if (this.numberInValue > this.min) {
          this.inputValue = this.numberInValue - 1;
          this.updateInput(this.input);
        } else {
          this.clearInterval();
        }
      }, 100);
    }
  }

  fixNumberValue() {
    if (this.inputValue !== this.oldValue) {
      if (this.match()) {
        if (!(this.numberInValue >= this.min && this.numberInValue <= this.max)) {
          this.inputValue = this.oldValue;
        }
      } else {
        if (this.oldValue) {
          this.inputValue = this.oldValue;
        } else {
          this.inputValue = this.min;
        }
      }
    }
    this.oldValue = this.inputValue;
  }

  valueChanged(e): void {
    e.stopPropagation();
    this.inputValue = e.target.value;
    this.updateInput(e.target);
  }

  updateInput(input) {
    this.fixNumberValue();
    Promise.resolve(null).then(
      () => {
        /** append unit */
        if (this.unit) {
          if (this.inputValue.toString().indexOf(this.unit) < 0) {
            this.inputValue = this.inputValue.toString() + this.unit;
          }
        }
        if (this.formControlName) {
          this.formControlName.control.setValue(this.numberInValue, {emitEvent: false});
        }

        input.value = this.inputValue;
        if (this.unit) {
          input.setSelectionRange(this.inputValue.length - 1, this.inputValue.length - 1);
        } else {
          input.setSelectionRange(this.inputValue.length, this.inputValue.length);
        }
      }
    );
  }

}
